home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 49
/
Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso
/
Aminet
/
util
/
misc
/
ReportPlus.lha
/
ReportPlus
/
source
/
f8.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-04-15
|
77KB
|
2,136 lines
#include <exec/types.h>
#include <exec/memory.h>
#include <proto/exec.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <proto/intuition.h>
#include <libraries/gadtools.h>
#include <proto/gadtools.h>
#include <dos/dos.h>
#include <dos/exall.h>
#include <dos/dostags.h>
#include <proto/dos.h>
#include <graphics/gfx.h>
#include <clib/graphics_protos.h>
#include <clib/alib_protos.h>
#include <libraries/asl.h>
#include <clib/asl_protos.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "rp.h"
#define ALL_REACTION_CLASSES
#include <reaction/reaction.h>
#define LIMIT_DIRS 8196
#define MAX_FILES (128 * 1024)
#define TRUNCATE 39
#define GRANULARITY_DIRS 10
#define GRANULARITY_FILES 10
/* Limitations:
LIMIT_DIRS (top-level list entries).
MAX_FILES (total files/dirs in path). */
MODULE void pop(void);
MODULE void push(STRPTR name, ULONG theindex);
MODULE void subdir(ULONG theindex);
MODULE void parent(void);
MODULE void root(void);
MODULE void pathasl(void);
MODULE void comma(ULONG value);
MODULE ABOOL dirasl(void);
MODULE void showduplicates(void);
MODULE void addduplicate(STRPTR path, STRPTR filename);
MODULE void writeline(void);
MODULE void killduplist(void);
MODULE void killsizelist(void);
MODULE void ghost(void);
MODULE void unghost(void);
MODULE void scale(ULONG bytes);
MODULE void __inline progressbar(ULONG level);
#define UNITOPTIONS 3 // counting from 0
MODULE STRPTR UnitOptions[UNITOPTIONS + 1] =
{ "Bytes",
"Kilobytes",
"Megabytes",
"Blocks"
};
MODULE struct ColumnInfo SizeColumnInfo[] =
{ { 75, // WORD ci_Width
"Pathname", // STRPTR ci_Title
0, // ULONG ci_Flags
},
{ 25,
"Size",
0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
to the right border of the relevant column). */
},
{ -1, (STRPTR) ~0, -1
} },
DupColumnInfo[] =
{ { 40, // WORD ci_Width
"Pathname", // STRPTR ci_Title
0, // ULONG ci_Flags
},
{ 10,
"Byte size",
0,
},
{ 10,
"Date",
0,
},
{ 10,
"Time",
0,
},
{ 30,
"Version",
0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
to the right border of the relevant column). */
},
{ -1, (STRPTR) ~0, -1
} };
IMPORT SBYTE page;
IMPORT TEXT globalname[VLONGFIELD + 1],
weekdaystring[10],
datestring[10],
timestring[9],
asldir[VLONGFIELD + 1],
aslresult[MEDFIELD + 1],
IOBuffer[LONGESTFIELD + 1];
IMPORT struct NewGadget Gadget;
IMPORT struct SharedStruct shared;
IMPORT struct Screen* ScreenPtr;
IMPORT struct Window* MainWindowPtr;
IMPORT struct ExAllData* EADataPtr;
IMPORT struct Menu* MenuPtr;
IMPORT Object* WinObject[FUNCTIONS + 1];
IMPORT ULONG increment;
AGLOBAL struct Gadget* size_gadgets[GIDS_8 + 1];
MODULE ABOOL DupNodes = FALSE,
SizeNodes = FALSE,
EmptyDupNodes = FALSE,
EmptySizeNodes = FALSE,
ram = FALSE;
MODULE struct List SizeList,
DupList,
EmptySizeList,
EmptyDupList;
MODULE STRPTR* PathnamePtr;
MODULE STRPTR* FilenamePtr;
MODULE STRPTR* StackPtr;
MODULE STRPTR* DirNamePtr;
MODULE ABOOL* IsDup;
MODULE BPTR TempHandle = NULL,
DirHandle = NULL,
LogFileHandle = NULL;
MODULE TEXT logstring[VLONGFIELD + 1],
liststring[5][VLONGFIELD + 1];
MODULE UBYTE valuestring[11],
commastring[14],
pathlength;
MODULE ULONG DirNamesAllocated = 0,
FileNamesAllocated = 0,
files = 0, // how many files have been found. Counting from 1.
status = STATUS_READY;
MODULE struct
{ ULONG entries, total, free, capacity, stackentries, blocksize,
finddup, slack, bytes[LIMIT_DIRS], topdir[LIMIT_DIRS], view,
numfiles, numdirs, log;
LONG type[LIMIT_DIRS];
TEXT oldpath[VLONGFIELD + 1], path[VLONGFIELD + 1], logfile[VLONGFIELD + 1];
} size;
AGLOBAL void size_init(void)
{ struct Node* ListBrowserNodePtr;
strcpy(size.path, "RAM:");
strcpy(size.logfile, "RAM:ReportPlus.txt");
size.finddup = size.slack = size.log = FALSE;
size.free = size.capacity = size.total = size.numfiles = size.numdirs = 0;
NewList(&SizeList);
NewList(&EmptySizeList);
if (!(ListBrowserNodePtr = AllocListBrowserNode
( 2, // columns
/* LBNCA_ tags are those that apply to the specific column. */
LBNA_Column, 0,
LBNA_Column, 1,
TAG_END
)))
{ rq("Can't create ReAction listbrowser.gadget node(s)!");
}
AddTail(&EmptySizeList, ListBrowserNodePtr); // AddTail() has no return code
EmptySizeNodes = TRUE;
NewList(&DupList);
NewList(&EmptyDupList);
if (!(ListBrowserNodePtr = AllocListBrowserNode
( 5, // columns
/* LBNCA_ tags are those that apply to the specific column. */
LBNA_Column, 0,
LBNA_Column, 1,
LBNA_Column, 2,
LBNA_Column, 3,
LBNA_Column, 4,
TAG_END
)))
{ rq("Can't create ReAction listbrowser.gadget node(s)!");
}
AddTail(&EmptyDupList, ListBrowserNodePtr); // AddTail() has no return code
EmptyDupNodes = TRUE;
}
AGLOBAL void size1(void)
{ struct Hook Hook8Struct;
struct List ChooserList;
struct ChooserNode* ChooserNodePtr[UNITOPTIONS + 1];
ULONG i;
TEXT freestring[13 + 1],
totalstring[13 + 1],
capacitystring[13 + 1],
filesstring[9 + 1],
dirsstring[9 + 1],
blocksizestring[9 + 1];
comma(size.numfiles);
strcpy(filesstring, commastring);
comma(size.numdirs);
strcpy(dirsstring, commastring);
comma(size.blocksize);
strcpy(blocksizestring, commastring);
scale(size.free);
strcpy(freestring, commastring);
scale(size.total);
strcpy(totalstring, commastring);
scale(size.capacity);
strcpy(capacitystring, commastring);
NewList(&ChooserList);
for (i = 0; i <= UNITOPTIONS; i++)
{ if (!(ChooserNodePtr[i] = (struct ChooserNode *) AllocChooserNode(CNA_Text, UnitOptions[i], TAG_DONE)))
{ rq("Can't allocate chooser node!");
}
AddTail(&ChooserList, (struct Node *) ChooserNodePtr[i]);
} // automatically freed by ReAction at DisposeObject() time
/* Create the window object. */
lockscreen();
gadtools();
InitHook(&Hook8Struct, Hook8Func, NULL);
/* We can't just use EmptyList for an empty columnar list, we
actually need a node (with the LBNA_Column tags) to be present.
LISTBROWSER_ScrollRaster seems not to be usable with
multi-column lists. */
if (!(WinObject[8] = NewObject(WINDOW_GetClass(), NULL,
// window
WA_PubScreen, ScreenPtr,
WA_ScreenTitle, "Report+",
WA_Title, "Report+: Path Size Report",
WA_Activate, TRUE,
WA_DepthGadget, TRUE,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_SizeGadget, TRUE,
WA_IDCMP, IDCMP_RAWKEY,
WINDOW_IDCMPHook, &Hook8Struct,
WINDOW_IDCMPHookBits, IDCMP_RAWKEY,
WINDOW_MenuStrip, MenuPtr,
WINDOW_Position, WPOS_FULLSCREEN,
WINDOW_ParentGroup, size_gadgets[GID_8_LY1] =
NewObject
( LAYOUT_GetClass(), NULL,
// root-layout
LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_DeferLayout, TRUE,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment, LALIGN_CENTER,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_AddImage,
NewObject
( LABEL_GetClass(), NULL,
LABEL_Text, "_Path:",
LABEL_Justification,LJ_LEFT,
TAG_END),
CHILD_WeightedWidth, 0,
LAYOUT_AddChild, size_gadgets[GID_8_ST1] =
NewObject
( STRING_GetClass(), NULL,
GA_ID, GID_8_ST1,
GA_RelVerify, TRUE,
STRINGA_TextVal, size.path,
STRINGA_MinVisible,35,
TAG_END),
LAYOUT_AddChild, size_gadgets[GID_8_BU1] =
NewObject(NULL, "button.gadget",
GA_ID, GID_8_BU1,
GA_RelVerify, TRUE,
BUTTON_AutoButton, BAG_POPFILE,
TAG_END),
CHILD_WeightedWidth, 0,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddChild, NewObject(LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment, LALIGN_CENTER,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_ShrinkWrap, TRUE,
LAYOUT_AddChild, size_gadgets[GID_8_CB1] =
NewObject
( CHECKBOX_GetClass(),NULL,
// checkbox
GA_ID, GID_8_CB1,
GA_RelVerify, TRUE,
GA_Text, "_Log to:",
GA_Selected, (BOOL) size.log,
TAG_END
),
CHILD_WeightedWidth, 0,
LAYOUT_AddChild, size_gadgets[GID_8_ST2] =
NewObject(STRING_GetClass(), NULL,
// string
GA_ID, GID_8_ST2,
GA_RelVerify, TRUE,
STRINGA_TextVal, size.logfile,
STRINGA_MinVisible,20,
GA_Disabled, !size.log,
TAG_END
),
LAYOUT_AddChild, size_gadgets[GID_8_BU3] =
NewObject
( NULL, "button.gadget",
// button
GA_ID, GID_8_BU3,
GA_RelVerify, TRUE,
BUTTON_AutoButton, BAG_POPFILE,
GA_Disabled, !size.log,
TAG_END
),
CHILD_WeightedWidth, 0,
TAG_END
),
CHILD_WeightedHeight, 0,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment, LALIGN_CENTER,
LAYOUT_BevelStyle, BVS_FIELD,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment, LALIGN_CENTER,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_AddChild, size_gadgets[GID_8_BU6] =
NewObject
( NULL, "button.gadget",
GA_ID, GID_8_BU6,
GA_RelVerify, TRUE,
GA_Text, "_Root",
TAG_END
),
CHILD_WeightedWidth, 50,
LAYOUT_AddChild, size_gadgets[GID_8_BU7] =
NewObject
( NULL, "button.gadget",
GA_ID, GID_8_BU7,
GA_RelVerify, TRUE,
GA_Text, "P_arent",
TAG_END
),
CHILD_WeightedWidth, 50,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddChild, size_gadgets[GID_8_LB2] =
NewObject
( LISTBROWSER_GetClass(),NULL,
GA_ID, GID_8_LB2,
GA_RelVerify, TRUE,
GA_TextAttr, Gadget.ng_TextAttr,
LISTBROWSER_Labels, (ULONG) &EmptySizeList,
LISTBROWSER_ColumnInfo,(ULONG) &SizeColumnInfo,
LISTBROWSER_ColumnTitles,TRUE,
TAG_END),
CHILD_WeightedHeight, 100,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_LEFT,
LAYOUT_HorizAlignment, LALIGN_RIGHT,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment, LALIGN_RIGHT,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_AddImage,
NewObject
( LABEL_GetClass(), NULL,
LABEL_Text, "Files:",
LABEL_Justification,LJ_CENTRE,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddImage,
NewObject
( LABEL_GetClass(), NULL,
LABEL_Text, "Directories:",
LABEL_Justification,LJ_CENTRE,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddImage,
NewObject
( LABEL_GetClass(), NULL,
LABEL_Text, "Block size:",
LABEL_Justification,LJ_CENTRE,
TAG_END),
CHILD_WeightedHeight, 0,
TAG_END),
CHILD_WeightedWidth, 0,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment, LALIGN_RIGHT,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_AddChild, size_gadgets[GID_8_ST6] =
NewObject
( STRING_GetClass(), NULL,
GA_ID, GID_8_ST6,
GA_ReadOnly, TRUE,
STRINGA_TextVal, filesstring,
STRINGA_MinVisible,13,
STRINGA_Justification,GACT_STRINGRIGHT,
GA_TextAttr, Gadget.ng_TextAttr,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddChild, size_gadgets[GID_8_ST7] =
NewObject
( STRING_GetClass(), NULL,
GA_ID, GID_8_ST7,
GA_ReadOnly, TRUE,
STRINGA_TextVal, dirsstring,
STRINGA_MinVisible,13,
STRINGA_Justification,GACT_STRINGRIGHT,
GA_TextAttr, Gadget.ng_TextAttr,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddChild, size_gadgets[GID_8_ST8] =
NewObject
( STRING_GetClass(), NULL,
GA_ID, GID_8_ST8,
GA_ReadOnly, TRUE,
STRINGA_TextVal, blocksizestring,
STRINGA_MinVisible,13,
STRINGA_Justification,GACT_STRINGRIGHT,
GA_TextAttr, Gadget.ng_TextAttr,
TAG_END),
CHILD_WeightedHeight, 0,
TAG_END),
CHILD_WeightedWidth, 0,
LAYOUT_AddImage, NewObject
( LABEL_GetClass(), NULL,
LABEL_Text, "",
TAG_END
),
CHILD_WeightedWidth, 100,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment, LALIGN_RIGHT,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_AddImage,
NewObject
( LABEL_GetClass(), NULL,
LABEL_Text, "Used in path:",
LABEL_Justification,LJ_RIGHT,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddImage,
NewObject
( LABEL_GetClass(), NULL,
LABEL_Text, "Free on volume:",
LABEL_Justification,LJ_RIGHT,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddImage,
NewObject
( LABEL_GetClass(), NULL,
LABEL_Text, "Volume capacity:",
LABEL_Justification,LJ_RIGHT,
TAG_END),
CHILD_WeightedHeight, 0,
TAG_END),
CHILD_WeightedWidth, 0,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment, LALIGN_RIGHT,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_AddChild, size_gadgets[GID_8_ST4] =
NewObject
( STRING_GetClass(), NULL,
GA_ID, GID_8_ST4,
GA_ReadOnly, TRUE,
STRINGA_TextVal, totalstring,
STRINGA_MinVisible,13,
STRINGA_Justification,GACT_STRINGRIGHT,
GA_TextAttr, Gadget.ng_TextAttr,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddChild, size_gadgets[GID_8_ST5] =
NewObject
( STRING_GetClass(), NULL,
GA_ID, GID_8_ST5,
GA_ReadOnly, TRUE,
STRINGA_TextVal, freestring,
STRINGA_MinVisible,13,
STRINGA_Justification,GACT_STRINGRIGHT,
GA_TextAttr, Gadget.ng_TextAttr,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddChild, size_gadgets[GID_8_ST3] =
NewObject
( STRING_GetClass(), NULL,
GA_ID, GID_8_ST3,
GA_ReadOnly, TRUE,
STRINGA_TextVal, capacitystring,
STRINGA_MinVisible,13,
STRINGA_Justification,GACT_STRINGRIGHT,
GA_TextAttr, Gadget.ng_TextAttr,
TAG_END),
CHILD_WeightedHeight, 0,
TAG_END),
CHILD_WeightedWidth, 0,
TAG_END),
CHILD_WeightedHeight, 0,
TAG_END),
CHILD_WeightedHeight, 70,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment, LALIGN_CENTER,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_AddImage,
NewObject
( LABEL_GetClass(), NULL,
// label
LABEL_Text, "_View as:",
LABEL_Justification,LJ_RIGHT,
TAG_END),
CHILD_WeightedWidth, 0,
LAYOUT_AddChild, size_gadgets[GID_8_CH1] =
NewObject
( CHOOSER_GetClass(),NULL,
GA_ID, GID_8_CH1,
GA_RelVerify, TRUE,
CHOOSER_PopUp, TRUE,
CHOOSER_Labels, &ChooserList,
CHOOSER_Selected, size.view,
TAG_END
),
CHILD_WeightedWidth, 0,
LAYOUT_AddImage, NewObject
( LABEL_GetClass(), NULL,
LABEL_Text, "",
TAG_END
),
CHILD_WeightedWidth, 100,
LAYOUT_AddChild, size_gadgets[GID_8_CB2] =
NewObject
( CHECKBOX_GetClass(),NULL,
// checkbox
GA_ID, GID_8_CB2,
GA_RelVerify, TRUE,
GA_Text, "Include _slack?",
GA_Selected, (BOOL) size.slack,
TAG_END),
CHILD_WeightedWidth, 0,
LAYOUT_AddChild, size_gadgets[GID_8_CB3] =
NewObject
( CHECKBOX_GetClass(),NULL,
// checkbox
GA_ID, GID_8_CB3,
GA_RelVerify, TRUE,
GA_Text, "Find _duplicates?",
GA_Selected, (BOOL) size.finddup,
TAG_END
),
CHILD_WeightedWidth, 0,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddChild, size_gadgets[GID_8_LB1] =
NewObject
( LISTBROWSER_GetClass(),NULL,
GA_ID, GID_8_LB1,
GA_ReadOnly, TRUE,
GA_TextAttr, Gadget.ng_TextAttr,
GA_Disabled, !size.finddup,
LISTBROWSER_Labels, (ULONG) &EmptyDupList,
LISTBROWSER_ColumnInfo,(ULONG) &DupColumnInfo,
LISTBROWSER_ColumnTitles,TRUE,
LISTBROWSER_HorizontalProp,TRUE,
LISTBROWSER_VirtualWidth,620 + 155,
TAG_END),
CHILD_WeightedHeight, 30,
LAYOUT_AddChild, size_gadgets[GID_8_FG1] =
NewObject
( FUELGAUGE_GetClass(), NULL,
GA_ID, GID_8_FG1,
GA_Text, "Ready.",
FUELGAUGE_Level, 0,
FUELGAUGE_Percent, FALSE,
FUELGAUGE_Justification,FGJ_CENTER,
TAG_END),
CHILD_WeightedHeight, 0,
LAYOUT_AddChild,
NewObject
( LAYOUT_GetClass(), NULL,
LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_HorizAlignment,LALIGN_CENTER,
LAYOUT_BevelStyle, BVS_NONE,
LAYOUT_AddChild, size_gadgets[GID_8_BU4] =
NewObject
( NULL, "button.gadget",
GA_ID, GID_8_BU4,
GA_RelVerify, TRUE,
GA_Text, "_Update",
TAG_END),
LAYOUT_AddChild, size_gadgets[GID_8_BU5] =
NewObject
( NULL, "button.gadget",
GA_ID, GID_8_BU5,
GA_RelVerify, TRUE,
GA_Text, "Stop",
GA_Disabled, TRUE,
TAG_END),
TAG_END),
CHILD_WeightedHeight, 0,
TAG_END)
)))
{ rq("Can't create ReAction objects!");
}
unlockscreen();
openwindow();
ActivateLayoutGadget(size_gadgets[GID_8_LY1], MainWindowPtr, NULL, (Object) size_gadgets[GID_8_ST1]);
loop();
closewindow();
size_exit();
}
AGLOBAL void updatesize(void)
{ BOOL more; // note that it is BOOL, not ABOOL
TEXT tempstring[VLONGFIELD + 1],
tempname[LONGFIELD + 1];
ULONG i, j, tempbytes, where;
LONG length, temptype; // these both MUST be signed
ABOOL failed = FALSE;
struct FileInfoBlock* FIBPtr = NULL;
struct InfoData* InfoDataPtr;
struct ExAllControl* eac;
struct ExAllData* ead;
struct Node* ListBrowserNodePtr;
/* 0: Ready
1: Reading directory...
! 2: Reading subdirectories...
3: Sorting contents...
![4: Matching duplicates...
[5: Condensing duplicates...
[6: Sorting duplicates...
![7: Examining duplicates...
[ = only for duplicates
! = can be aborted by user
*/
if (SizeNodes)
{ clearlist(&SizeList);
SizeNodes = FALSE;
}
if (!DirNamePtr)
{ if (!(DirNamePtr = AllocVec(LIMIT_DIRS * sizeof(STRPTR), NULL)))
{ rq("Out of memory!");
} }
// 1: Ghost relevant gadgets, for duration of the operation.
ghost();
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Min, 0,
FUELGAUGE_Max, 100,
FUELGAUGE_Level, 25,
GA_Text, "Reading directory...",
TAG_END
); // we don't know how many files in advance...
// 2: Now get a Lock() on the path.
size.stackentries = size.entries = size.numdirs = size.numfiles = 0;
/* From RKRM I&A, p. 65: */
if
( !(DirHandle = (BPTR) Lock(size.path, ACCESS_READ))
|| !(FIBPtr = AllocDosObject(DOS_FIB, NULL))
|| !( Examine(DirHandle, FIBPtr))
|| (FIBPtr->fib_DirEntryType <= 0) // if not a directory
)
{ failed = TRUE;
}
strcpy(size.oldpath, size.path);
if (FIBPtr)
{ FreeDosObject(DOS_FIB, FIBPtr);
// FIBPtr = NULL;
}
if (failed)
{ DisplayBeep(ScreenPtr);
unghost();
strcpy(size.path, size.oldpath);
SetGadgetAttrs
( size_gadgets[GID_8_ST1], MainWindowPtr, NULL,
STRINGA_TextVal, size.path,
TAG_END
);
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Level, 0,
GA_Text, "Failed!",
TAG_END
);
return;
}
SetGadgetAttrs
( size_gadgets[GID_8_ST1], MainWindowPtr, NULL,
STRINGA_TextVal, size.path,
TAG_END
);
/* 3: Now we call Info() to ascertain the free bytes.
InfoDataPtr must be longword-aligned. */
if (!(InfoDataPtr = AllocVec(sizeof(struct InfoData), MEMF_CLEAR)))
{ rq("Out of memory!");
}
if (Info(DirHandle, InfoDataPtr))
{ size.blocksize = InfoDataPtr->id_BytesPerBlock;
size.free =
(InfoDataPtr->id_NumBlocks - InfoDataPtr->id_NumBlocksUsed) *
InfoDataPtr->id_BytesPerBlock;
size.capacity =
InfoDataPtr->id_NumBlocks *
InfoDataPtr->id_BytesPerBlock;
} else
{ rq("Can't get volume info!");
}
FreeVec(InfoDataPtr);
// InfoDataPtr = NULL;
comma(size.blocksize);
SetGadgetAttrs // "dirs"
( size_gadgets[GID_8_ST8], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
/* 4: Now we are ready to begin the main part of the operation.
size.topdir[] = the 'owning' top-level directory for this subdir.
Top-level dirs are owned by themselves.
size.bytes[] = the size of this top-level directory/file.
size.entries = how many top-level dirs, ie. how many names in the
listview gadget.
size.path = the path (drive, partition, etc.) the user is doing
the report on.
size.stackentries = the current size of the stack.
DirNamesAllocated = the number of allocated chunks for the
topdir names. */
if (!( StackPtr = AllocVec(LIMIT_DIRS * sizeof(STRPTR), NULL)))
{ rq("Out of memory!");
}
files = size.total = 0;
if (size.finddup)
{ if (!( PathnamePtr = AllocVec(MAX_FILES * sizeof(STRPTR), NULL)))
{ rq("Out of memory!");
}
if (!( FilenamePtr = AllocVec(MAX_FILES * sizeof(STRPTR), NULL)))
{ rq("Out of memory!");
}
if (!( IsDup = AllocVec(MAX_FILES * sizeof(ABOOL) , NULL)))
{ rq("Out of memory!");
} }
// This must be allocated with AllocDosObject()
if (!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL)))
{ rq("Can't allocate DOS object!");
}
eac->eac_LastKey = 0;
do
{ more = ExAll(DirHandle, (struct ExAllData *) EADataPtr, 4096, ED_SIZE, eac);
if (!more && IoErr() != ERROR_NO_MORE_ENTRIES)
{ FreeDosObject(DOS_EXALLCONTROL, eac);
eac = NULL;
rq("Can't examine path!");
}
if (eac->eac_Entries == 0)
{ ; /* ExAll() failed normally with no entries */
continue; /* more is USUALLY zero */
}
// OK, ExAll() has generated up to 2K of data.
ead = (struct ExAllData *) EADataPtr;
do
{ /* use ead here */
if (ead->ed_Type == -3 || ead->ed_Type == 2) // if a normal file or normal directory (ie. not a link)
{ size.entries++;
if (size.entries == LIMIT_DIRS)
{ FreeDosObject(DOS_EXALLCONTROL, eac);
eac = NULL;
rq("Overflow!");
}
size.type[size.entries] = ead->ed_Type;
if (size.entries > DirNamesAllocated)
{ if (!(DirNamePtr[DirNamesAllocated + 1] = AllocMem(VLONGFIELD, MEMF_PUBLIC)))
{ FreeDosObject(DOS_EXALLCONTROL, eac);
eac = NULL;
rq("Out of memory!");
}
DirNamesAllocated++;
}
strcpy(DirNamePtr[size.entries], ead->ed_Name);
if (ead->ed_Type == 2) /* +2 is dir, +3 is softlink, -3 is file */
{ size.numdirs++;
if (!(size.numdirs % GRANULARITY_DIRS))
{ comma(size.numdirs);
SetGadgetAttrs
( size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
}
size.bytes[size.entries] = 0;
strcpy(tempstring, size.path);
if (!AddPart(tempstring, ead->ed_Name, VLONGFIELD))
{ FreeDosObject(DOS_EXALLCONTROL, eac);
eac = NULL;
rq("Can't add filename to pathname!");
}
push(tempstring, size.entries);
} else
{ size.numfiles++;
if (!(size.numfiles % GRANULARITY_FILES))
{ comma(size.numfiles);
SetGadgetAttrs
( size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
}
addduplicate("", ead->ed_Name);
if (size.slack)
{ if (ead->ed_Size % size.blocksize == 0)
{ size.bytes[size.entries] = (ead->ed_Size / size.blocksize) * size.blocksize;
size.total += (ead->ed_Size / size.blocksize) * size.blocksize;
} else
{ size.bytes[size.entries] = ((ead->ed_Size / size.blocksize) + 1) * size.blocksize;
size.total += ((ead->ed_Size / size.blocksize) + 1) * size.blocksize;
} }
else
{ size.bytes[size.entries] = ead->ed_Size;
size.total += ead->ed_Size;
} } }
/* get next ead */
ead = ead->ed_Next;
} while(ead);
} while(more);
FreeDosObject(DOS_EXALLCONTROL, eac);
// eac = NULL;
UnLock(DirHandle);
DirHandle = NULL;
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Min, 0,
FUELGAUGE_Max, 100,
FUELGAUGE_Level, 50,
GA_Text, "Reading subdirectories...",
TAG_END
);
pop();
// Now handle the list.
killsizelist();
if (status == STATUS_BUSY)
{ /* size.entries is the actual number of entries. The array elements are
from 1 to size.entries.
bubble sort routine */
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Min, 0,
FUELGAUGE_Max, size.entries - 2,
GA_Text, "Sorting contents...",
TAG_END
);
setbar(size.entries - 2);
for (i = size.entries; i >= 2; i--)
{ progressbar(size.entries - 1);
for (j = 2; j <= i; j++)
{ if (size.bytes[j - 1] < size.bytes[j])
{ // swap them
tempbytes = size.bytes[j - 1];
size.bytes[j - 1] = size.bytes[j];
size.bytes[j] = tempbytes;
temptype = size.type[j - 1];
size.type[j - 1] = size.type[j];
size.type[j] = temptype;
strcpy(tempname, DirNamePtr[j - 1]);
strcpy(DirNamePtr[j - 1], DirNamePtr[j]);
strcpy(DirNamePtr[j], tempname);
} } }
getdate();
if (size.log)
{ strcpy(logstring, "Path: \"");
strcat(logstring, size.path);
strcat(logstring, "\" at ");
strcat(logstring, timestring);
strcat(logstring, " on ");
strcat(logstring, weekdaystring);
strcat(logstring, " ");
strcat(logstring, datestring);
strcat(logstring, ":\n");
if (!(LogFileHandle = (BPTR) Open(size.logfile, MODE_READWRITE)))
rq("Can't open file for appending!");
Seek(LogFileHandle, 0, OFFSET_END);
writeline();
}
for (i = 1; i <= size.entries; i++)
{ scale(size.bytes[i]);
if (size.log)
{ if (size.type[i] == 2)
{ strcpy(logstring, "*");
} else
{ strcpy(logstring, " ");
}
strncat(logstring, DirNamePtr[i], TRUNCATE);
if (strlen(DirNamePtr[i]) < TRUNCATE)
{ length = TRUNCATE - strlen(DirNamePtr[i]);
for (j = 1; j <= length; j++)
{ strcat(logstring, " ");
} }
strcat(logstring, " ");
strcat(logstring, commastring);
strcat(logstring, "\n");
writeline();
}
if (size.type[i] == 2)
{ strcpy(liststring[0], "*");
} else
{ strcpy(liststring[0], " ");
}
strcat(liststring[0], DirNamePtr[i]);
for (j = 0; j <= 13; j++)
{ if (commastring[j] != ' ')
{ where = j; // where is index of first non-space character
break;
} }
strcpy(liststring[1], &commastring[where]);
if (!(ListBrowserNodePtr = AllocListBrowserNode
( 2, // columns,
LBNA_Column, 0,
LBNCA_CopyText, TRUE,
LBNCA_Text, liststring[0],
LBNA_Column, 1,
LBNCA_CopyText, TRUE,
LBNCA_Text, &commastring[where],
LBNCA_Justification, LCJ_RIGHT,
TAG_END
)))
{ rq("Can't create ReAction listbrowser.gadget node(s)!");
}
AddTail(&SizeList, ListBrowserNodePtr); // AddTail() has no return code
SizeNodes = TRUE;
}
scale(size.total);
SetGadgetAttrs // "used in path"
( size_gadgets[GID_8_ST4], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
scale(size.free);
SetGadgetAttrs // "free on volume"
( size_gadgets[GID_8_ST5], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
scale(size.capacity);
SetGadgetAttrs // "volume capacity"
( size_gadgets[GID_8_ST3], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
comma(size.numfiles);
SetGadgetAttrs // "files"
( size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
comma(size.numdirs);
SetGadgetAttrs // "dirs"
( size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
if (size.log)
{ strcpy(logstring, "\nUsed in path: ");
scale(size.total);
strcat(logstring, commastring);
strcat(logstring, "\nFree on volume: "); // these must be adjusted according to TRUNCATE
scale(size.free);
strcat(logstring, commastring);
strcat(logstring, "\nVolume capacity: "); // these must be adjusted according to TRUNCATE
scale(size.capacity);
strcat(logstring, commastring);
strcat(logstring, "\nFiles: "); // these must be adjusted according to TRUNCATE
comma(size.numfiles);
strcat(logstring, commastring);
strcat(logstring, "\nDirectories: "); // these must be adjusted according to TRUNCATE
comma(size.numdirs);
strcat(logstring, commastring);
strcat(logstring, "\nBlock size: "); // these must be adjusted according to TRUNCATE
comma(size.blocksize);
strcat(logstring, commastring);
strcat(logstring, "\n\n");
writeline();
}
SetGadgetAttrs
( size_gadgets[GID_8_LB2], MainWindowPtr, NULL,
LISTBROWSER_Labels, &SizeList,
TAG_END
);
showduplicates();
} else
{ SetGadgetAttrs // "used in path"
( size_gadgets[GID_8_ST4], MainWindowPtr, NULL,
STRINGA_TextVal, "-",
TAG_END
);
SetGadgetAttrs // "free on volume"
( size_gadgets[GID_8_ST5], MainWindowPtr, NULL,
STRINGA_TextVal, "-",
TAG_END
);
SetGadgetAttrs // "volume capacity"
( size_gadgets[GID_8_ST3], MainWindowPtr, NULL,
STRINGA_TextVal, "-",
TAG_END
);
SetGadgetAttrs // "files"
( size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
STRINGA_TextVal, "-",
TAG_END
);
SetGadgetAttrs // "directories"
( size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
STRINGA_TextVal, "-",
TAG_END
);
SetGadgetAttrs // "block size"
( size_gadgets[GID_8_ST8], MainWindowPtr, NULL,
STRINGA_TextVal, "-",
TAG_END
);
killsizelist();
killduplist();
}
unghost();
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Min, 0,
FUELGAUGE_Max, 100,
FUELGAUGE_Level, 100,
GA_Text, "Done",
TAG_END
);
if (LogFileHandle)
{ Close(LogFileHandle);
LogFileHandle = NULL;
}
while (FileNamesAllocated)
{ FreeMem(StackPtr[FileNamesAllocated], VLONGFIELD);
StackPtr[FileNamesAllocated--] = NULL;
}
FreeVec(StackPtr);
StackPtr = NULL;
// We need the DirNamePtr[] array to remain valid, because
// the user can click on the listview gadget.
}
MODULE void subdir(ULONG topdir)
{ BOOL more;
TEXT tempstring[VLONGFIELD + 1];
struct ExAllControl* eac;
struct ExAllData* ead;
/* Instead of passing a pointer to the path, we use a global string.
There are memory corruption problems if you pass pointers to variables
which are really local to other functions.
This is dynamically allocated as it must be at least word-aligned;
also remember not to allocate large arrays on the stack. */
if (!(DirHandle = (BPTR) Lock(globalname, ACCESS_READ)))
{ DisplayBeep(ScreenPtr);
return;
}
if (!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL)))
{ UnLock(DirHandle);
DirHandle = NULL;
rq("Can't allocate DOS object!");
}
eac->eac_LastKey = 0;
do
{ more = ExAll(DirHandle, (struct ExAllData *) EADataPtr, 4096, ED_SIZE, eac);
if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES))
{ FreeDosObject(DOS_EXALLCONTROL, eac);
eac = NULL;
UnLock(DirHandle);
DirHandle = NULL;
rq("Can't examine path!");
}
if (eac->eac_Entries == 0)
{ ; /* ExAll() failed normally with no entries */
continue; /* more is USUALLY zero */
}
ead = (struct ExAllData *) EADataPtr;
do
{ /* use ead here */
if (ead->ed_Type == 2) /* +2 is dir, +3 is softlink, -3 is file */
{ size.numdirs++;
if (!(size.numdirs % GRANULARITY_DIRS))
{ comma(size.numdirs);
SetGadgetAttrs
( size_gadgets[GID_8_ST7], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
}
strcpy(tempstring, globalname);
if (!AddPart(tempstring, ead->ed_Name, VLONGFIELD))
{ FreeDosObject(DOS_EXALLCONTROL, eac);
eac = NULL;
UnLock(DirHandle);
DirHandle = NULL;
rq("Can't add filename to pathname!");
}
push(tempstring, topdir);
} elif (ead->ed_Type == -3) // if it's a file
{ size.numfiles++;
if (!(size.numfiles % GRANULARITY_FILES))
{ comma(size.numfiles);
SetGadgetAttrs
( size_gadgets[GID_8_ST6], MainWindowPtr, NULL,
STRINGA_TextVal, commastring,
TAG_END
);
}
addduplicate(&globalname[pathlength], ead->ed_Name);
if (size.slack)
{ if (ead->ed_Size % size.blocksize == 0)
{ size.bytes[topdir] += (ead->ed_Size / size.blocksize) * size.blocksize;
size.total += (ead->ed_Size / size.blocksize) * size.blocksize;
} else
{ size.bytes[topdir] += ((ead->ed_Size / size.blocksize) + 1) * size.blocksize;
size.total += ((ead->ed_Size / size.blocksize) + 1) * size.blocksize;
} }
else
{ size.bytes[topdir] += ead->ed_Size;
size.total += ead->ed_Size;
} }
/* get next ead */
ead = ead->ed_Next;
} while(ead);
} while(more);
FreeDosObject(DOS_EXALLCONTROL, eac);
// eac = NULL;
UnLock(DirHandle);
DirHandle = NULL;
// don't call pop() yourself!
}
MODULE void pop(void)
{ ULONG breakval;
pathlength = strlen(size.path);
while (size.stackentries && status == STATUS_BUSY)
{ size.stackentries--;
strcpy(globalname, StackPtr[size.stackentries + 1]);
subdir(size.topdir[size.stackentries + 1]);
breakval = ra_checkbreak();
if (breakval == 2)
cleanexit(EXIT_SUCCESS);
elif (breakval == 1)
status = STATUS_STOPPING;
} }
MODULE void push(STRPTR name, ULONG theindex)
{ size.stackentries++;
if (size.stackentries == LIMIT_DIRS)
rq("Overflow!");
if (size.stackentries > FileNamesAllocated)
{ if (!(StackPtr[FileNamesAllocated + 1] = AllocMem(VLONGFIELD, MEMF_PUBLIC)))
rq("Out of memory!");
FileNamesAllocated++;
}
strcpy(StackPtr[size.stackentries], name);
size.topdir[size.stackentries] = theindex;
}
AGLOBAL void size_loop(ULONG gid)
{ ULONG code;
STRPTR stringptr;
switch(gid)
{
case GID_8_BU1: // path ASL
pathasl();
break;
case GID_8_BU3:
asl("~(#?.info)");
SetGadgetAttrs // `Log to file:' (string)
( size_gadgets[GID_8_ST2], MainWindowPtr, NULL,
STRINGA_TextVal, size.logfile,
TAG_END);
break;
case GID_8_BU4: // update
updatesize();
break;
// GID_8_BU5 is stop
case GID_8_BU6:
root();
break;
case GID_8_BU7:
parent();
break;
case GID_8_ST1: // path string
if (!(GetAttr
( STRINGA_TextVal, size_gadgets[GID_8_ST1], (ULONG *) &stringptr
)))
{ rq("Unsupported inquiry!"); // should never happen
}
strcpy(size.path, stringptr);
updatesize();
break;
case GID_8_ST2: // output string
if (!(GetAttr
( STRINGA_TextVal, size_gadgets[GID_8_ST2], (ULONG *) &stringptr
)))
{ rq("Unsupported inquiry!"); // should never happen
}
strcpy(size.logfile, stringptr);
break;
case GID_8_CB1:
if (!(GetAttr
( GA_Selected, size_gadgets[GID_8_CB1], &size.log
)))
{ rq("Unsupported inquiry!"); // should never happen
}
SetGadgetAttrs // `Log to file:' (string)
( size_gadgets[GID_8_ST2], MainWindowPtr, NULL,
GA_Disabled, !size.log,
TAG_END
);
/* For some reason, we need to explicitly refresh the string gadget
visuals here */
RefreshGadgets((struct Gadget *) size_gadgets[GID_8_ST2], MainWindowPtr, NULL);
SetGadgetAttrs // `Log to file:' (ASL button)
( size_gadgets[GID_8_BU3], MainWindowPtr, NULL,
GA_Disabled, !size.log,
TAG_END
);
if (size.log)
{ ActivateLayoutGadget(size_gadgets[GID_8_LY1], MainWindowPtr, NULL, (Object) size_gadgets[GID_8_ST2]);
}
break;
case GID_8_CB2:
if (!(GetAttr
( GA_Selected, size_gadgets[GID_8_CB2], (ULONG *) &size.slack
)))
{ rq("Unsupported inquiry!"); // should never happen
}
break;
case GID_8_CB3:
if (!(GetAttr
( GA_Selected, size_gadgets[GID_8_CB3], (ULONG *) &size.finddup
)))
{ rq("Unsupported inquiry!"); // should never happen
}
SetGadgetAttrs
( size_gadgets[GID_8_LB1], MainWindowPtr, NULL,
GA_Disabled, !size.finddup,
TAG_END
);
break;
case GID_8_CH1:
if (!(GetAttr
( CHOOSER_Selected, size_gadgets[GID_8_CH1], (ULONG *) &size.view
)))
{ rq("Unsupported inquiry!"); // should never happen
}
break;
case GID_8_LB2:
/* code is the position within the list, starting from 0. */
if (!(GetAttr
( LISTBROWSER_Selected, size_gadgets[GID_8_LB2], (ULONG *) &code
)))
{ rq("Unsupported inquiry!"); // should never happen
}
code++;
if (code <= size.entries && size.type[code] == 2)
{ if (!(AddPart(size.path, DirNamePtr[code], VLONGFIELD + 1)))
{ rq("Can't add filename to pathname!");
} else
{ updatesize();
} }
break;
default:
break;
} }
AGLOBAL void size_exit(void)
{ if (TempHandle)
{ UnLock(TempHandle);
TempHandle = NULL;
}
if (DirHandle)
{ UnLock(DirHandle);
DirHandle = NULL;
}
if (LogFileHandle)
{ Close(LogFileHandle);
LogFileHandle = NULL;
}
// Only call this if the list gadget is detached or not present.
// (ie. after closewindow()).
if (SizeNodes)
{ clearlist(&SizeList);
SizeNodes = FALSE;
}
if (DupNodes)
{ clearreactionlist(&DupList);
DupNodes = FALSE;
}
while (FileNamesAllocated)
{ FreeMem(StackPtr[FileNamesAllocated], VLONGFIELD);
StackPtr[FileNamesAllocated--] = NULL;
}
if (StackPtr)
{ FreeVec(StackPtr);
StackPtr = NULL;
}
while ( DirNamesAllocated)
{ FreeMem(DirNamePtr[DirNamesAllocated], VLONGFIELD);
DirNamePtr[DirNamesAllocated--] = NULL;
}
if (DirNamePtr)
{ FreeVec(DirNamePtr);
DirNamePtr = NULL;
} }
AGLOBAL void size_die(void)
{ if (EmptySizeNodes)
{ clearreactionlist(&EmptySizeList);
EmptySizeNodes = FALSE;
}
if (EmptyDupNodes)
{ clearreactionlist(&EmptyDupList);
EmptyDupNodes = FALSE;
}
IOBuffer[0] = size.log;
IOBuffer[6] = size.finddup;
IOBuffer[21] = size.slack;
IOBuffer[22] = (UBYTE) size.view;
}
AGLOBAL void size_config(void)
{ size.log = (ULONG) IOBuffer[0];
size.finddup = (ULONG) IOBuffer[6];
size.slack = (ULONG) IOBuffer[21];
size.view = (ULONG) IOBuffer[22];
}
MODULE void parent(void)
{ BPTR DirHandle,
ParentHandle;
if (!(DirHandle = (BPTR) Lock(size.path, ACCESS_READ)))
rq("Can't lock directory!");
if (!(ParentHandle = ParentDir(DirHandle)))
{ /* It returned a NULL lock; ie. a lock on SYS:
That is not what we want. */
ParentHandle = DirHandle;
}
if (!NameFromLock(ParentHandle, size.path, VLONGFIELD))
rq("Can't get name from lock!");
UnLock(DirHandle);
// DirHandle = NULL;
updatesize();
}
MODULE void root(void)
{ BPTR DirHandle,
ParentHandle;
ABOOL rootdone = FALSE;
if (!(DirHandle = (BPTR) Lock(size.path, ACCESS_READ)))
rq("Can't lock directory!");
do
{ if (!(ParentHandle = ParentDir(DirHandle)))
{ /* It returned a NULL lock; ie. a lock on SYS:
That is not what we want. */
ParentHandle = DirHandle;
rootdone = TRUE;
} else DirHandle = ParentHandle;
} while (!rootdone);
if (!NameFromLock(ParentHandle, size.path, VLONGFIELD))
rq("Can't get name from lock!");
UnLock(DirHandle);
// DirHandle = NULL;
updatesize();
}
MODULE void pathasl(void)
{ strcpy(asldir, size.path);
if (dirasl()) // path for ASL must be valid?
{ strcpy(size.path, aslresult);
SetGadgetAttrs
( size_gadgets[GID_8_ST1], MainWindowPtr, NULL,
STRINGA_TextVal, size.path,
TAG_END
);
updatesize();
} }
MODULE void comma(ULONG value)
{ ABOOL yes = FALSE;
strcpy(commastring, " , , , ");
// 1 5 9
valuestring[ 0] = '0' + (value / 1000000000);
value %= 1000000000;
if (valuestring[ 0] != '0')
{ commastring[0] = valuestring[0];
yes = TRUE;
} else
{ commastring[ 0] = ' ';
commastring[ 1] = ' ';
}
valuestring[ 1] = '0' + (value / 100000000);
value %= 100000000;
if (yes || valuestring[1] != '0')
{ commastring[2] = valuestring[1];
yes = TRUE;
} else commastring[2] = ' ';
valuestring[ 2] = '0' + (value / 10000000);
value %= 10000000;
if (yes || valuestring[2] != '0')
{ commastring[3] = valuestring[2];
yes = TRUE;
} else commastring[3] = ' ';
valuestring[ 3] = '0' + (value / 1000000);
value %= 1000000;
if (yes || valuestring[3] != '0')
{ commastring[4] = valuestring[3];
yes = TRUE;
} else
{ commastring[4] = ' ';
commastring[5] = ' ';
}
valuestring[ 4] = '0' + (value / 100000);
value %= 100000;
if (yes || valuestring[4] != '0')
{ commastring[6] = valuestring[4];
yes = TRUE;
} else commastring[6] = ' ';
valuestring[ 5] = '0' + (value / 10000);
value %= 10000;
if (yes || valuestring[5] != '0')
{ commastring[7] = valuestring[5];
yes = TRUE;
} else commastring[7] = ' ';
valuestring[ 6] = '0' + (value / 1000);
value %= 1000;
if (yes || valuestring[6] != '0')
{ commastring[8] = valuestring[6];
yes = TRUE;
} else
{ commastring[8] = ' ';
commastring[9] = ' ';
}
valuestring[ 7] = '0' + (value / 100);
value %= 100;
if (yes || valuestring[7] != '0')
{ commastring[10] = valuestring[7];
yes = TRUE;
} else commastring[10] = ' ';
valuestring[ 8] = '0' + (value / 10);
value %= 10;
if (yes || valuestring[8] != '0')
{ commastring[11] = valuestring[8];
// yes = TRUE;
} else commastring[11] = ' ';
valuestring[ 9] = '0' + value ;
commastring[12] = valuestring[9];
}
MODULE ABOOL dirasl(void)
{ struct FileRequester* ASLRqPtr;
ABOOL success;
if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, "~(#?.info)", ASL_Window, MainWindowPtr, ASL_ExtFlags1, FIL1F_NOFILES, TAG_DONE)))
{ rq("Can't create ASL request!");
}
if (AslRequestTags(ASLRqPtr, ASL_Dir, asldir, ASL_Hail, "Report+ path selector", ASL_FuncFlags, FILF_PATGAD, TAG_DONE))
{ strcpy(aslresult, ASLRqPtr->rf_Dir);
success = TRUE;
} else success = FALSE;
FreeAslRequest(ASLRqPtr);
return(success);
}
MODULE void showduplicates(void)
{ ABOOL found = FALSE,
started = FALSE,
success;
TEXT pathnamestring[VLONGFIELD + 1],
commandstring[VLONGFIELD + 1],
lastfilename[VLONGFIELD + 1];
ULONG breakval, i, j, k, where,
firstpen, secondpen, currentpen, dups;
LONG length;
STRPTR tempPathnamePtr, tempFilenamePtr;
struct DateTime DateTime;
struct FileInfoBlock* FIBPtr;
struct Node* ListBrowserNodePtr;
DateTime.dat_Format = FORMAT_DOS;
DateTime.dat_Flags = NULL;
DateTime.dat_StrDay = NULL;
DateTime.dat_StrDate = datestring;
DateTime.dat_StrTime = timestring;
if (size.finddup)
{ killduplist();
lockscreen();
firstpen = FindColor
( ScreenPtr->ViewPort.ColorMap,
0xDDDDDDDD,
0xDDDDDDDD,
0xDDDDDDDD,
-1
);
secondpen = FindColor
( ScreenPtr->ViewPort.ColorMap,
0xAAAAAAAA,
0xAAAAAAAA,
0xAAAAAAAA,
-1
);
unlockscreen();
currentpen = firstpen;
if (size.log)
{ strcpy(logstring, "Duplicates found:\n");
writeline();
}
/* Now we iterate through the complete file list (last entry index
of files). For each file (i), we look at every other file (j). As
soon as we find a matching file, we add the file (i) to the
duplicate file list. */
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Min, 1,
FUELGAUGE_Max, files,
GA_Text, "Matching duplicates...",
TAG_DONE
);
setbar(files);
for (i = 1; i <= files; i++)
{ progressbar(i);
breakval = ra_checkbreak();
if (breakval == 2)
{ cleanexit(EXIT_SUCCESS);
} elif (breakval == 1)
{ status = STATUS_STOPPING;
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
GA_Text, "Stopping...",
TAG_END
);
break;
}
// if the user doesn't want us to stop...
for (j = 1; j <= files; j++)
{ if (i != j && !stricmp(FilenamePtr[i], FilenamePtr[j]))
{ found = TRUE; // we found (at least one) match
IsDup[i] = TRUE;
break;
} } }
if (status == STATUS_BUSY)
{ SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Min, 1,
FUELGAUGE_Max, files,
GA_Text, "Condensing duplicates...",
TAG_END
);
setbar(files);
// condense list
dups = 0;
for (i = 1; i <= files; i++)
{ progressbar(i);
if (IsDup[i])
{ dups++;
FilenamePtr[dups] = FilenamePtr[i];
PathnamePtr[dups] = PathnamePtr[i];
IsDup[dups] = IsDup[i];
} else
{ FreeVec(PathnamePtr[i]);
FreeVec(FilenamePtr[i]);
} }
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Min, 2,
FUELGAUGE_Max, dups,
GA_Text, "Sorting duplicates...",
TAG_END
);
setbar(dups);
// bubble sort routine
for (i = dups; i >= 2; i--)
{ progressbar(dups - i);
for (j = 2; j <= i; j++)
{ if (stricmp(FilenamePtr[j - 1], FilenamePtr[j]) > 0)
{ // swap them
tempPathnamePtr = PathnamePtr[j - 1];
PathnamePtr[j - 1] = PathnamePtr[j];
PathnamePtr[j] = tempPathnamePtr;
tempFilenamePtr = FilenamePtr[j - 1];
FilenamePtr[j - 1] = FilenamePtr[j];
FilenamePtr[j] = tempFilenamePtr;
} } }
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Min, 0,
FUELGAUGE_Max, dups,
FUELGAUGE_Level, 0,
GA_Text, "Examining duplicates...",
TAG_END
);
setbar(dups);
NewList(&DupList);
for (i = 1; i <= dups; i++)
{ progressbar(i);
breakval = ra_checkbreak();
if (breakval == 2)
{ cleanexit(EXIT_SUCCESS);
} elif (breakval == 1)
{ status = STATUS_STOPPING;
SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
GA_Text, "Stopping...",
TAG_END
);
break;
}
// begin creating the line of text
if (PathnamePtr[i][0] == '/')
{ strcpy(liststring[0], &(PathnamePtr[i][1]));
} else
{ strcpy(liststring[0], PathnamePtr[i]);
}
strcpy(logstring, " ");
strcat(logstring, liststring[0]);
if (strlen(logstring) > TRUNCATE)
{ *(logstring + TRUNCATE) = 0; // truncate
}
length = TRUNCATE + 2 - strlen(logstring);
if (length >= 1)
{ for (k = 1; k <= length; k++)
{ strcat(logstring, " ");
} }
strcpy(pathnamestring, size.path);
if (PathnamePtr[i][0] != '/')
{ if (!AddPart(pathnamestring, PathnamePtr[i], 256))
{ rq("AddPart() failed!");
} }
else
{ if (!AddPart(pathnamestring, &PathnamePtr[i][1], 256))
{ rq("AddPart() failed!");
} }
success = FALSE;
// now get size and date of file
if (DirHandle = (BPTR) Lock(pathnamestring, ACCESS_READ))
{ if (FIBPtr = AllocDosObject(DOS_FIB, NULL))
{ success = TRUE;
if (Examine(DirHandle, FIBPtr))
{ comma(FIBPtr->fib_Size);
strcat(logstring, commastring);
for (j = 0; j <= 13; j++)
{ if (commastring[j] != ' ')
{ where = j; // where is index of first non-space character
break;
} }
strcpy(liststring[1], &commastring[where]);
} else
{ strcpy(liststring[1], "?");
strcat(logstring, " ?");
}
strcat(logstring, " ");
DateTime.dat_Stamp = FIBPtr->fib_Date;
if (DateToStr(&DateTime))
{ strcpy(liststring[2], datestring);
strcpy(liststring[3], timestring);
} else
{ strcpy(liststring[2], " ?");
strcpy(liststring[3], " ?");
}
strcat(logstring, liststring[2]);
strcat(logstring, " ");
strcat(logstring, liststring[3]);
strcat(logstring, " ");
FreeDosObject(DOS_FIB, FIBPtr);
// FIBPtr = NULL;
UnLock(DirHandle);
DirHandle = NULL;
} }
if (!success)
{ strcpy(liststring[1], " ?");
strcpy(liststring[2], " ?");
strcpy(liststring[3], " ?");
strcat(logstring, liststring[1]);
strcat(logstring, " ");
strcat(logstring, liststring[2]);
strcat(logstring, " ");
strcat(logstring, liststring[3]);
strcat(logstring, " ");
}
getversion(pathnamestring, liststring[4]);
strcat(logstring, liststring[4]);
// now get the file version
if (ram)
{ strcpy(commandstring, "RAM:Version ");
} else
{ strcpy(commandstring, "Version ");
}
strcat(commandstring, pathnamestring);
strcat(commandstring, " >T:ReportPlus.temp");
if (!SystemTags(commandstring, SYS_Output, Open("NIL:", MODE_NEWFILE), TAG_DONE))
{ readordie("T:ReportPlus.temp");
for (k = 0; k <= VLONGFIELD; k++)
{ if (IOBuffer[k] == LF)
{ IOBuffer[k] = 0;
break;
} }
strcpy(liststring[4], IOBuffer);
} else
{ strcpy(liststring[4], "?");
}
strcat(logstring, liststring[4]);
if (started)
{ if (stricmp(FilenamePtr[i], lastfilename))
{ if (currentpen == firstpen)
{ currentpen = secondpen;
} else currentpen = firstpen;
} }
else started = TRUE;
if (!(ListBrowserNodePtr = AllocListBrowserNode
( 5, // columns,
LBNA_Column, 0,
LBNA_Flags, LBFLG_CUSTOMPENS,
LBNCA_FGPen, BLACK,
LBNCA_BGPen, currentpen,
LBNCA_CopyText, TRUE,
LBNCA_Text, liststring[0],
LBNA_Column, 1,
LBNA_Flags, LBFLG_CUSTOMPENS,
LBNCA_FGPen, BLACK,
LBNCA_BGPen, currentpen,
LBNCA_CopyText, TRUE,
LBNCA_Text, liststring[1],
LBNCA_Justification, LCJ_RIGHT,
LBNA_Column, 2,
LBNA_Flags, LBFLG_CUSTOMPENS,
LBNCA_FGPen, BLACK,
LBNCA_BGPen, currentpen,
LBNCA_CopyText, TRUE,
LBNCA_Text, liststring[2],
LBNA_Column, 3,
LBNA_Flags, LBFLG_CUSTOMPENS,
LBNCA_FGPen, BLACK,
LBNCA_BGPen, currentpen,
LBNCA_CopyText, TRUE,
LBNCA_Text, liststring[3],
LBNA_Column, 4,
LBNA_Flags, LBFLG_CUSTOMPENS,
LBNCA_FGPen, BLACK,
LBNCA_BGPen, currentpen,
LBNCA_CopyText, TRUE,
LBNCA_Text, liststring[4],
TAG_END
)))
{ rq("Can't create ReAction listbrowser.gadget node(s)!");
}
AddTail(&DupList, ListBrowserNodePtr); // AddTail() has no return code
DupNodes = TRUE;
strcpy(lastfilename, FilenamePtr[i]);
if (size.log) // write to logfile
{ strcat(logstring, "\n");
writeline();
} }
for (i = 1; i <= dups; i++)
{ FreeVec(PathnamePtr[i]);
FreeVec(FilenamePtr[i]);
} }
else
{ for (i = 1; i <= files; i++)
{ FreeVec(PathnamePtr[i]);
FreeVec(FilenamePtr[i]);
} }
files = 0;
FreeVec(IsDup);
IsDup = NULL;
FreeVec(PathnamePtr);
PathnamePtr = NULL;
FreeVec(FilenamePtr);
FilenamePtr = NULL;
DeleteFile("T:ReportPlus.temp"); /* returns FALSE for failure */
if (size.log)
{ if (!found)
{ strcpy(logstring, " None\n");
}
strcat(logstring, "\n");
writeline();
}
SetGadgetAttrs
( size_gadgets[GID_8_LB1], MainWindowPtr, NULL,
LISTBROWSER_Labels, &DupList,
TAG_END
);
} }
MODULE void addduplicate(STRPTR path, STRPTR filename)
{ TEXT tablestring[257];
if (size.finddup)
{ files++;
if (files >= MAX_FILES)
{ rq("Too many files!");
}
IsDup[files] = FALSE;
if (!(FilenamePtr[files] = AllocVec(strlen(filename) + 1, NULL)))
{ rq("Out of memory!");
}
strcpy(FilenamePtr[files], filename);
strcpy(tablestring, path);
if (!AddPart(tablestring, filename, 256))
{ rq("AddPart() failed!");
}
if (!(PathnamePtr[files] = AllocVec(strlen(tablestring) + 1, NULL)))
{ rq("Out of memory!");
}
strcpy(PathnamePtr[files], tablestring);
/* size.path path filename PathnamePtr[] FilenamePtr[]
"SYS:Tools" "Commodities/" "AutoPoint" "Commodities/AutoPoint" "AutoPoint" */
} }
MODULE void writeline(void)
{ /* The file is opened just before the first call to writeline()
(when the date, time, etc. is written). Then we keep the file open
and do our scan. Then we write out the results a line at a time,
then the free and total bytes.
If we are also doing duplicates, we now do our thinking,
write the results a line at a time, then close the file. */
if (FPuts(LogFileHandle, logstring))
{ Close(LogFileHandle);
LogFileHandle = NULL;
rq("Can't append to file!");
} }
MODULE void killsizelist(void)
{ SetGadgetAttrs
( size_gadgets[GID_8_LB2], MainWindowPtr, NULL,
LISTBROWSER_Labels, &EmptySizeList,
TAG_END
);
if (SizeNodes)
{ clearreactionlist(&SizeList);
SizeNodes = FALSE;
} }
MODULE void killduplist(void)
{ SetGadgetAttrs
( size_gadgets[GID_8_LB1], MainWindowPtr, NULL,
LISTBROWSER_Labels, &EmptyDupList,
TAG_END
);
if (DupNodes)
{ clearreactionlist(&DupList);
DupNodes = FALSE;
} }
AGLOBAL ULONG Hook8Func(struct Hook *h, VOID *o, VOID *msg)
{ /* "When the hook is called, the data argument points to the
window object and message argument to the IntuiMessage." */
UWORD code, qual;
ULONG scroll;
geta4(); // wait till here before doing anything
code = ((struct IntuiMessage *) msg)->Code;
qual = ((struct IntuiMessage *) msg)->Qualifier;
switch(code)
{
case SCAN_HELP:
if (status == STATUS_READY)
{ helpabout();
}
break;
case SCAN_ESCAPE:
if (status == STATUS_READY)
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ cleanexit(EXIT_SUCCESS);
} else page = 0;
} else
{ // assert(status == STATUS_BUSY);
status = STATUS_STOPPING;
}
break;
case SCAN_P:
ActivateLayoutGadget(size_gadgets[GID_8_LY1], MainWindowPtr, NULL, (Object) size_gadgets[GID_8_ST1]);
break;
case SCAN_V:
if (status == STATUS_READY)
{ if (!(qual & IEQUALIFIER_LSHIFT) && !(qual & IEQUALIFIER_RSHIFT))
{ if (size.view < UNITOPTIONS)
size.view++;
else size.view = 0;
} else
{ if (size.view > 0)
size.view--;
else size.view = UNITOPTIONS;
}
SetGadgetAttrs
( size_gadgets[GID_8_CH1], MainWindowPtr, NULL,
CHOOSER_Selected, size.view,
TAG_END
);
}
break;
case SCAN_PERIOD:
pathasl();
break;
case SCAN_UP:
if (qual & IEQUALIFIER_CONTROL)
{ scroll = LBP_TOP;
} elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
{ scroll = LBP_PAGEUP;
} else scroll = LBP_LINEUP;
break;
case SCAN_DOWN:
if (qual & IEQUALIFIER_CONTROL)
{ scroll = LBP_BOTTOM;
} elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
{ scroll = LBP_PAGEDOWN;
} else scroll = LBP_LINEDOWN;
break;
default:
break;
}
if (code == SCAN_UP || code == SCAN_DOWN)
{ SetGadgetAttrs
( size_gadgets[GID_8_LB2], // pointer to gadget
MainWindowPtr, // pointer to window (not window object!)
NULL, // pointer to requester
LISTBROWSER_Position, scroll, // tags
TAG_DONE // done
);
}
return(1);
}
MODULE void ghost(void)
{ status = STATUS_BUSY;
SetGadgetAttrs // "update"
( size_gadgets[GID_8_BU4], MainWindowPtr, NULL,
GA_Disabled, TRUE,
TAG_END
);
SetGadgetAttrs // "stop"
( size_gadgets[GID_8_BU5], MainWindowPtr, NULL,
GA_Disabled, FALSE,
TAG_END
);
}
MODULE void unghost(void)
{ status = STATUS_READY;
SetGadgetAttrs // "update"
( size_gadgets[GID_8_BU4], MainWindowPtr, NULL,
GA_Disabled, FALSE,
TAG_END
);
SetGadgetAttrs // "stop"
( size_gadgets[GID_8_BU5], MainWindowPtr, NULL,
GA_Disabled, TRUE,
TAG_END
);
}
MODULE void scale(ULONG bytes)
{ if (size.view == 0) // bytes
{ comma(bytes);
} elif (size.view == 1) // kilobytes
{ comma(bytes / 1024);
} elif (size.view == 2) // megabytes
{ comma(bytes / 1048576);
} else
{ // assert(size.view == 3); // blocks
// assert(size.blocksize); // to avoid division by zero
comma(bytes / size.blocksize);
if (bytes % size.blocksize)
{ comma((bytes / size.blocksize) + 1);
} else // exactly on a block boundary
{ comma(bytes / size.blocksize);
} } }
MODULE void __inline progressbar(ULONG level)
{ if (!(level % increment))
{ SetGadgetAttrs
( size_gadgets[GID_8_FG1], MainWindowPtr, NULL,
FUELGAUGE_Level, level,
TAG_END
);
} }